/*
 * @Author: lmk
 * @Date: 2022-05-26 00:08:05
 * @LastEditTime: 2022-06-05 11:03:11
 * @LastEditors: lmk
 * @Description: 全局下拉刷新列表组件
 */
import crud from '@/api/crud';
import useUrlState from '@ahooksjs/use-url-state';
import { ErrorBlock, InfiniteScroll, List, NavBar, PullToRefresh } from 'antd-mobile';
import React, { Key, ReactNode } from 'react';
import { useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
interface IProps {
  url: string; // url请求
  renderView: (record: any, index: Key) => JSX.Element; // 渲染的元素
  title: string // 标题
  hideTitle?: boolean // 是否显示标题
  layout?: 'grid' | 'flex' // 布局
  headerView?: () => JSX.Element // 头部
  headHeight?: number // 头部高度
  listType?: 'card' | 'list' // 列表类型
  navRight?: ReactNode // 右侧导航
}
const ListView = (props: IProps) => {
  const [data, setData] = useState<string[]>([])
  const [hasMore, setHasMore] = useState(true)
  const [isLoading, setIsLoading] = useState(false)
  const [page, setPage] = useState(1)
  const [error, setError] = useState(false)
  const [state] = useUrlState()
  const loadMore = async () => {
    if (isLoading || error) return;
    setIsLoading(true)
    setError(false)
    return fetchData().then(res => {
      setData([...data, ...res.records])
      setPage(page + 1)
      setHasMore(res.records.length >= pageSize)
    }).finally(() => {
      setIsLoading(false)
    })
  }
  const onRefresh = async () => {
    if (isLoading) return;
    setIsLoading(true)
    setError(false)
    fetchData().then(res => {
      setPage(1)
      setHasMore(true)
      setData([...res.records])
    }).finally(() => {
      setIsLoading(false)
    })
  }
  const pageSize = 20;
  const fetchData = async () => {
    try {
      const data = await crud.customRequest({
        url: props.url,
        method: 'post',
        data: {
          current: page,
          size: pageSize,
          ...state
        }
      })
      return data
    } catch (error) {
      if (page === 1) {
        setError(true)
      }
      return Promise.reject(error)
    }
  }
  const setting = props.navRight ? { right: props.navRight } : {};
  const navigate = useNavigate();
  const location = useLocation();
  const locationState = location.state as {formType:string}
  const goBack = () => {
    locationState?.formType==='homePage' ? navigate(-1) : navigate('/',{
      replace: true,
    })
  }
  return <div className='flex flex-col h-screen'>
    {/* 头部 */}
    {!props.hideTitle && <NavBar onBack={goBack} className='fixed left-0 right-0 top-0 z-10 nav-bg'
    {...setting}>
      <span className="text-lg font-bold text-primary">{props.title}</span>
    </NavBar>}
    {/* 下拉上拉列表 */}
    {!error && <div className='flex-1 pt-16'>
    {props.headerView?.()}
      <PullToRefresh
        headHeight={props.headHeight}
        onRefresh={onRefresh}>
        <div className={props.listType === 'card' ? 'bg-white m-5 rounded-2xl' : ''}>
          {data.length > 0 && <List style={{ '--border-top': 'none', '--border-bottom': 'none' }}>
            <div className={`${props.layout === 'grid' ? 'grid grid-cols-2' : 'flex flex-col'} p-5 gap-3`}>
              {data.map(props.renderView)}
            </div>
          </List>}
        </div>
        <InfiniteScroll loadMore={loadMore} hasMore={hasMore} />
      </PullToRefresh>
    </div>}
    {/* 错误空状态 */}
    {error && <div className='flex-auto flex items-center justify-center'>
      <ErrorBlock status='disconnected' />
    </div>}
  </div>
};

export default ListView;
